import os
import json
import requests
import datetime
from flask import Flask, Blueprint, request, render_template, url_for, redirect, flash, jsonify, session
from flask_cors import CORS
from werkzeug.utils import secure_filename
import random

# 删除导入骨骼问卷分析服务的代码行
# from services.skeleton_service import analyze_survey

app = Flask(__name__)
# 启用CORS，允许所有域的跨域请求
CORS(app, resources={r"/*": {"origins": "*"}})

app.secret_key = 'your_secret_key'  # 用于flash消息和session

# 配置上传文件的保存路径和允许的文件类型
UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'uploads')
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 限制上传文件大小为16MB

# 舌诊API配置
TONGUE_API_URL = "https://ali-market-tongue-detect-v2.macrocura.com/diagnose/face-tongue/result/"
TONGUE_API_APPCODE = "13f14f83c7324bedbaf8bc52aa974738"

# 添加骨骼问卷分析函数
def analyze_survey(survey_data):
    """
    分析骨骼问卷结果，返回风险评估和建议
    
    参数:
    survey_data (dict): 包含以下键的问卷数据字典
        age: 年龄（整数）
        gender: 性别（'男'或'女'）
        height: 身高（厘米，浮点数）
        weight: 体重（公斤，浮点数）
        light_injury: 是否轻微碰撞就会骨折（'是'或'否'）
        parent_fracture: 父母是否有骨折史（'是'或'否'）
        hormone_medication: 是否长期服用激素类药物（'是'或'否'）
        height_decrease: 近年是否身高变矮超过3cm（'是'或'否'）
        alcohol: 是否经常饮酒（'是'或'否'）
        smoking: 是否吸烟（'是'或'否'）
        diarrhea: 是否经常腹泻（'是'或'否'）
        early_menopause: (女性)是否绝经早于45岁（'是'或'否'）
        no_menstruation: (女性)是否超过3个月没有来月经（'是'或'否'）
        impotence: (男性)是否存在阳痿（'是'或'否'）
        poor_appetite: 是否经常没胃口或因各种原因吃得比同龄人少（'是'或'否'）
        low_calcium_diet: 是否几乎不喝牛奶、酸奶，也很少吃奶酪、豆腐、豆浆（'是'或'否'）
        low_sunlight: 是否很少户外活动或出门时裹得严实（'是'或'否'）
        long_term_ppi: 是否长期服用"拉唑"类胃药（'是'或'否'）
        special_medication: 是否因过敏、皮肤病或癫痫长期服药（'是'或'否'）
        underweight: 是否一直很瘦或最近体重无缘无故下降（'是'或'否'）
        back_pain: 是否经常感觉腰背隐隐作痛（'是'或'否'）
        forward_bending: 是否背部开始有点往前弯（'是'或'否'）
        walking_instability: 是否感觉走路不如以前稳当（'是'或'否'）
        thyroid_issue: 是否被诊断过甲状腺功能异常或甲状旁腺问题（'是'或'否'）
    
    返回:
    dict: 包含分析结果的字典
    """
    # 提取基本数据
    age = survey_data.get('age', 0)
    gender = survey_data.get('gender', '男')
    height = survey_data.get('height', 0) / 100  # 转换为米
    weight = survey_data.get('weight', 0)
    
    # 计算BMI
    bmi = weight / (height * height) if height > 0 else 0
    bmi_status = '正常'
    bmi_comment = '您的BMI在正常范围内，请保持健康的生活习惯。'
    
    if bmi < 18.5:
        bmi_status = '偏瘦'
        bmi_comment = '您的BMI偏低，可能存在骨质疏松风险，建议适当增加体重，并保证营养均衡。'
    elif bmi > 24:
        bmi_status = '偏胖'
        bmi_comment = '您的BMI偏高，过重会增加骨骼负担，建议控制饮食并增加运动量。'
    
    # 初始分数为100，每个风险因素扣减一定分数
    score = 100
    risk_factors = []
    
    # 检查各项风险因素
    if survey_data.get('light_injury') == '是':
        score -= 15
        risk_factors.append('轻微碰撞就会骨折，可能存在骨质疏松')
    
    if survey_data.get('parent_fracture') == '是':
        score -= 10
        risk_factors.append('父母有骨折史，存在遗传风险因素')
    
    if survey_data.get('hormone_medication') == '是':
        score -= 10
        risk_factors.append('长期服用激素类药物，可能影响骨质密度')
    
    if survey_data.get('height_decrease') == '是':
        score -= 15
        risk_factors.append('近年身高变矮超过3cm，可能是骨质疏松导致椎体压缩')
    
    if survey_data.get('alcohol') == '是':
        score -= 5
        risk_factors.append('经常饮酒，可能影响钙质吸收')
    
    if survey_data.get('smoking') == '是':
        score -= 8
        risk_factors.append('吸烟，会降低血液中的雌激素水平，加速骨量流失')
    
    if survey_data.get('diarrhea') == '是':
        score -= 5
        risk_factors.append('经常腹泻，可能影响营养物质的吸收')
    
    # 性别特定风险因素
    if gender == '女':
        if survey_data.get('early_menopause') == '是':
            score -= 12
            risk_factors.append('绝经早于45岁，雌激素水平下降导致骨量流失加速')
        
        if survey_data.get('no_menstruation') == '是':
            score -= 10
            risk_factors.append('超过3个月没有来月经，可能是雌激素水平异常')
    else:  # 男性
        if survey_data.get('impotence') == '是':
            score -= 10
            risk_factors.append('存在阳痿，可能与睾酮水平低有关，影响骨健康')
    
    # 处理新增问题11-20
    if survey_data.get('poor_appetite') == '是':
        score -= 8
        risk_factors.append('食欲不佳或进食量少，可能导致营养摄入不足')
    
    if survey_data.get('low_calcium_diet') == '是':
        score -= 10
        risk_factors.append('很少摄入富含钙质的食物，钙质摄入不足')
    
    if survey_data.get('low_sunlight') == '是':
        score -= 8
        risk_factors.append('缺乏阳光照射，维生素D合成不足')
    
    if survey_data.get('long_term_ppi') == '是':
        score -= 7
        risk_factors.append('长期服用"拉唑"类胃药，可能影响钙的吸收')
    
    if survey_data.get('special_medication') == '是':
        score -= 6
        risk_factors.append('长期服用可能影响骨代谢的特殊药物')
    
    if survey_data.get('underweight') == '是':
        score -= 8
        risk_factors.append('体重过轻或近期无故体重下降，骨量可能不足')
    
    if survey_data.get('back_pain') == '是':
        score -= 6
        risk_factors.append('腰背经常隐痛，可能是骨质疏松早期信号')
    
    if survey_data.get('forward_bending') == '是':
        score -= 12
        risk_factors.append('背部开始驼背，可能是骨质疏松引起的脊柱变形')
    
    if survey_data.get('walking_instability') == '是':
        score -= 10
        risk_factors.append('行走不稳，跌倒风险增加，易发生骨折')
    
    if survey_data.get('thyroid_issue') == '是':
        score -= 10
        risk_factors.append('甲状腺或甲状旁腺功能异常，影响钙代谢和骨健康')
    
    # 年龄调整
    if age > 60:
        score -= min(20, (age - 60) * 0.5)  # 超过60岁每年减少0.5分，最多减20分
        risk_factors.append('年龄超过60岁，骨量自然流失增加')
    
    # BMI调整
    if bmi < 18.5:
        score -= 8
        risk_factors.append('体重偏轻，骨密度可能较低')
    elif bmi > 30:
        score -= 5
        risk_factors.append('体重过重，增加骨骼负担')
    
    # 确保分数在0-100范围内
    score = max(0, min(100, score))
    
    # 如果是满分，随机设置为80-85之间的值
    if score == 100:
        score = random.randint(80, 85)
    
    # 计算骨密度评估指数 - 根据公式：(体重kg-年龄)×0.2
    bone_density_index = (weight - age) * 0.2
    
    # 根据骨密度指数判断风险级别
    bone_density_risk = ''
    bone_density_comment = ''
    
    if bone_density_index > -1:
        bone_density_risk = '低风险'
        bone_density_comment = '您的骨质疏松风险较低。'
    elif bone_density_index < -4:
        bone_density_risk = '高风险'
        bone_density_comment = '您的骨质疏松风险较高，建议尽快开始治疗。'
    else:
        bone_density_risk = '中风险'
        bone_density_comment = '您的骨质疏松风险为中等水平，建议定期进行骨密度检测。'
    
    # 根据分数确定健康等级
    health_level = ''
    level_description = ''
    
    if score >= 90:
        health_level = '优'
        level_description = '您的骨骼健康状况非常好，骨质疏松风险很低。'
    elif score >= 75:
        health_level = '良'
        level_description = '您的骨骼健康状况良好，骨质疏松风险较低。'
    elif score >= 60:
        health_level = '中'
        level_description = '您的骨骼健康状况一般，存在一定的骨质疏松风险。'
    elif score >= 40:
        health_level = '差'
        level_description = '您的骨骼健康状况较差，骨质疏松风险较高。'
    else:
        health_level = '极差'
        level_description = '您的骨骼健康状况极差，骨质疏松风险非常高。'
    
    # 生成健康建议
    dietary_advice = [
        '确保每日摄入足够的钙质，成年人每日需要约1000-1200毫克钙',
        '多吃富含维生素D的食物，如鱼类、蛋黄等，帮助钙质吸收',
        '保持均衡饮食，摄入足够的蛋白质和微量元素'
    ]
    
    exercise_advice = [
        '定期进行负重运动，如步行、爬楼梯或举重，以增强骨密度',
        '进行平衡训练，减少跌倒风险',
        '每周至少进行150分钟中等强度的有氧运动'
    ]
    
    lifestyle_advice = [
        '避免吸烟和过量饮酒',
        '确保充足的阳光照射，每天至少15-20分钟',
        '定期进行骨密度检测，尤其是高危人群'
    ]
    
    # 根据风险因素添加个性化建议
    if '长期服用激素类药物，可能影响骨质密度' in risk_factors:
        dietary_advice.append('在医生指导下补充钙剂和维生素D')
        lifestyle_advice.append('定期监测骨密度变化')
    
    if '经常饮酒，可能影响钙质吸收' in risk_factors:
        lifestyle_advice.append('减少酒精摄入，避免过量饮酒')
    
    if '吸烟，会降低血液中的雌激素水平，加速骨量流失' in risk_factors:
        lifestyle_advice.append('戒烟或减少吸烟量')
    
    if gender == '女' and ('绝经早于45岁，雌激素水平下降导致骨量流失加速' in risk_factors or 
                          '超过3个月没有来月经，可能是雌激素水平异常' in risk_factors):
        dietary_advice.append('增加植物雌激素摄入，如豆制品')
        lifestyle_advice.append('咨询医生关于激素替代疗法的可能性')
    
    if gender == '男' and '存在阳痿，可能与睾酮水平低有关，影响骨健康' in risk_factors:
        lifestyle_advice.append('咨询医生关于激素水平检测')
    
    # 为新增问题添加个性化建议
    if '食欲不佳或进食量少，可能导致营养摄入不足' in risk_factors:
        dietary_advice.append('采用少食多餐方式，每餐确保优质蛋白和富含钙的食物')
        dietary_advice.append('考虑使用营养补充品增加营养摄入')
    
    if '很少摄入富含钙质的食物，钙质摄入不足' in risk_factors:
        dietary_advice.append('增加奶制品摄入，如牛奶、酸奶、奶酪，每日1-2份')
        dietary_advice.append('多吃钙强化豆制品、小鱼干、芝麻、杏仁等富钙食物')
        dietary_advice.append('在医生指导下考虑钙补充剂')
    
    if '缺乏阳光照射，维生素D合成不足' in risk_factors:
        lifestyle_advice.append('每天适当日晒，最好在上午10点-下午3点之间，每次15-30分钟')
        dietary_advice.append('增加富含维生素D的食物，如鱼油、蛋黄')
        dietary_advice.append('咨询医生关于维生素D补充的必要性')
    
    if '长期服用"拉唑"类胃药，可能影响钙的吸收' in risk_factors:
        lifestyle_advice.append('咨询医生是否可以调整胃药的剂量或类型')
        dietary_advice.append('增加钙和维生素D的摄入，弥补药物可能导致的吸收不足')
    
    if '长期服用可能影响骨代谢的特殊药物' in risk_factors:
        lifestyle_advice.append('请勿自行停药，与医生讨论药物对骨骼影响和可能的替代方案')
        dietary_advice.append('强化钙和维生素D摄入，并考虑骨密度监测')
    
    if '体重过轻或近期无故体重下降，骨量可能不足' in risk_factors:
        dietary_advice.append('适当增加热量和蛋白质摄入，维持健康体重')
        lifestyle_advice.append('结合营养师咨询，制定合理增重计划')
    
    if '腰背经常隐痛，可能是骨质疏松早期信号' in risk_factors:
        exercise_advice.append('进行核心肌群训练，增强腰背肌力')
        lifestyle_advice.append('注意姿势，避免弯腰负重')
        lifestyle_advice.append('如果疼痛加重，及时就医评估')
    
    if '背部开始驼背，可能是骨质疏松引起的脊柱变形' in risk_factors:
        exercise_advice.append('定期进行脊柱伸展和姿势矫正练习')
        lifestyle_advice.append('使用符合人体工程学的椅子和床垫')
        lifestyle_advice.append('建议尽快进行骨密度检测，评估是否需要药物干预')
    
    if '行走不稳，跌倒风险增加，易发生骨折' in risk_factors:
        exercise_advice.append('进行平衡训练，如太极、瑜伽中的站立姿势')
        lifestyle_advice.append('配备合适的鞋子，避免过于光滑的地面')
        lifestyle_advice.append('家中清除可能导致绊倒的障碍物，必要时安装扶手')
    
    if '甲状腺或甲状旁腺功能异常，影响钙代谢和骨健康' in risk_factors:
        lifestyle_advice.append('定期复查甲状腺/甲状旁腺功能')
        lifestyle_advice.append('按医嘱调整药物剂量，确保激素水平正常')
        dietary_advice.append('特别注意钙和维生素D的摄入，可能需要个性化补充方案')
    
    # 根据骨密度风险级别添加特定建议
    if bone_density_risk == '高风险':
        lifestyle_advice.append('建议尽快就医进行骨密度检测(DXA)')
        dietary_advice.append('在医生指导下服用钙剂和维生素D补充剂')
    elif bone_density_risk == '中风险':
        lifestyle_advice.append('建议在近期进行骨密度检测')
    
    # 汇总分析结果
    result = {
        'score': round(score, 1),
        'health_level': health_level,
        'level_description': level_description,
        'risk_factors': risk_factors,
        'bmi': round(bmi, 1),
        'bmi_status': bmi_status,
        'bmi_comment': bmi_comment,
        'bone_density': {
            'index': round(bone_density_index, 1),
            'risk': bone_density_risk,
            'comment': bone_density_comment
        },
        'advice': {
            'dietary': dietary_advice,
            'exercise': exercise_advice,
            'lifestyle': lifestyle_advice
        }
    }
    
    return result

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# 自定义函数：生成使用bioeyoi.com域名的URL
def get_custom_url(filename):
    # 先生成本地URL
    local_url = url_for('static', filename=f'uploads/{filename}', _external=True)
    # 替换域名部分
    return local_url.replace('http://127.0.0.1', 'http://bioeyoi.com')

# 调用舌诊API分析图片
def analyze_tongue_image(image_url, gender):
    headers = {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip, deflate, br',
        'Authorization': f'APPCODE {TONGUE_API_APPCODE}',
        'Connection': 'keep-alive',
        'Content-Type': 'application/json; charset=UTF-8',
        'User-Agent': 'PostmanRuntime-ApipostRuntime/1.1.0'
    }
    
    data = {
        "scene": 2,
        "tf_image": image_url,
        "gender": gender
    }
    
    try:
        response = requests.post(TONGUE_API_URL, headers=headers, json=data)
        response.raise_for_status()  # 检查HTTP错误
        result = response.json()
        
        # 检查返回结果是否有效
        if not result or 'data' not in result or not result['data']:
            return {"error": "图片不符合要求，无法进行舌诊分析", "invalid_image": True}
        
        return result
    except Exception as e:
        print(f"API调用错误: {str(e)}")
        return {"error": str(e)}

# 删除图片文件
def delete_uploaded_file(filepath):
    try:
        if os.path.exists(filepath):
            os.remove(filepath)
            print(f"已删除文件: {filepath}")
            return True
    except Exception as e:
        print(f"删除文件失败: {str(e)}")
    return False

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload_file():
    # 检查是否有文件上传
    if 'file' not in request.files:
        flash('没有选择文件')
        return redirect(request.url)
    
    file = request.files['file']
    gender = request.form.get('gender', '男')  # 获取性别，默认为"男"
    
    # 如果用户没有选择文件，浏览器也会提交一个没有文件名的空文件
    if file.filename == '':
        flash('没有选择文件')
        return redirect(request.url)
    
    # 检查文件类型是否允许
    if file and allowed_file(file.filename):
        # 使用时间戳命名文件，避免重名
        timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        ext = file.filename.rsplit('.', 1)[1].lower()
        filename = f"{timestamp}.{ext}"
        
        # 确保目录存在
        os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
        
        # 保存文件
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)
        
        # 生成自定义URL，使用bioeyoi.com域名
        file_url = get_custom_url(filename)
        
        # 调用舌诊API
        analysis_result = analyze_tongue_image(file_url, gender)
        
        # 分析完成后删除上传的图片
        delete_uploaded_file(file_path)
        
        # 根据请求类型返回结果
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify({
                'success': True, 
                'file_url': file_url,
                'analysis_result': analysis_result
            })
        else:
            # 如果图片不符合要求，显示相应信息
            if 'error' in analysis_result and 'invalid_image' in analysis_result:
                flash(analysis_result['error'])
            else:
                flash('图片上传成功，已完成舌诊分析')
                
            return render_template(
                'diagnosis.html', 
                file_url=file_url, 
                analysis_result=analysis_result,
                gender=gender
            )
    else:
        flash('不允许的文件类型')
        return redirect(request.url)

# 添加API端点，提供跨域访问舌诊分析功能，按照前端要求的格式返回数据
@app.route('/api/analyze', methods=['POST'])
def api_analyze():
    data = request.json
    
    if not data or 'image_url' not in data:
        return jsonify({
            'code': 40000,
            'success': False,
            'msg': '缺少图片URL参数',
            'data': None,
            'reason': '请提供有效的image_url参数',
            'log_id': datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        }), 400
    
    image_url = data.get('image_url')
    gender = data.get('gender', '男')  # 默认为男性
    
    try:
        # 调用舌诊API
        analysis_result = analyze_tongue_image(image_url, gender)
        
        # 检查API调用是否成功
        if 'error' in analysis_result:
            error_msg = '图片不符合要求，无法进行舌诊分析' if 'invalid_image' in analysis_result else '舌诊API调用失败'
            return jsonify({
                'code': 50000,
                'success': False,
                'msg': error_msg,
                'data': None,
                'reason': analysis_result['error'],
                'log_id': datetime.datetime.now().strftime('%Y%m%d%H%M%S')
            }), 500
        
        # 按照前端要求的格式返回数据
        return jsonify({
            'code': 20000,
            'success': True,
            'msg': '成功',
            'data': analysis_result.get('data', analysis_result),
            'reason': None,
            'log_id': datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        })
    
    except Exception as e:
        return jsonify({
            'code': 50000,
            'success': False,
            'msg': '服务器处理错误',
            'data': None,
            'reason': str(e),
            'log_id': datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        }), 500

# 骨骼问卷蓝图
skeleton_bp = Blueprint('skeleton', __name__, url_prefix='/skeleton')

@skeleton_bp.route('/')
def index():
    """显示骨骼问卷首页"""
    return render_template('skeleton/index.html')

@skeleton_bp.route('/questions')
def questions():
    """显示问卷问题页"""
    return render_template('skeleton/questions.html')

@skeleton_bp.route('/submit', methods=['POST'])
def submit():
    """处理问卷提交"""
    # 获取表单数据
    survey_data = {
        'age': request.form.get('age', type=int),
        'gender': request.form.get('gender'),
        'height': request.form.get('height', type=float),
        'weight': request.form.get('weight', type=float),
        'light_injury': request.form.get('light_injury'),
        'parent_fracture': request.form.get('parent_fracture'),
        'hormone_medication': request.form.get('hormone_medication'),
        'height_decrease': request.form.get('height_decrease'),
        'alcohol': request.form.get('alcohol'),
        'smoking': request.form.get('smoking'),
        'diarrhea': request.form.get('diarrhea'),
        'early_menopause': request.form.get('early_menopause'),
        'no_menstruation': request.form.get('no_menstruation'),
        'impotence': request.form.get('impotence'),
        'poor_appetite': request.form.get('poor_appetite'),
        'low_calcium_diet': request.form.get('low_calcium_diet'),
        'low_sunlight': request.form.get('low_sunlight'),
        'long_term_ppi': request.form.get('long_term_ppi'),
        'special_medication': request.form.get('special_medication'),
        'underweight': request.form.get('underweight'),
        'back_pain': request.form.get('back_pain'),
        'forward_bending': request.form.get('forward_bending'),
        'walking_instability': request.form.get('walking_instability'),
        'thyroid_issue': request.form.get('thyroid_issue')
    }
    
    # 分析问卷结果
    result = analyze_survey(survey_data)
    
    # 保存结果到会话中，以便在结果页显示
    session['survey_result'] = result
    
    return redirect(url_for('skeleton.result'))

@skeleton_bp.route('/result')
def result():
    """显示问卷结果页"""
    # 从会话中获取结果
    result = session.get('survey_result')
    if not result:
        flash('请先完成问卷调查')
        return redirect(url_for('skeleton.questions'))
    
    return render_template('skeleton/result.html', result=result)

# 注册骨骼问卷蓝图
app.register_blueprint(skeleton_bp)

# 在首页添加指向骨骼问卷的链接
@app.context_processor
def inject_skeleton_url():
    """向所有模板注入骨骼问卷的URL"""
    return {'skeleton_url': url_for('skeleton.index')}

if __name__ == '__main__':
    app.run(debug=True) 